package com.xxx.adapter;

import com.xxx.request.RpcRequest;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import org.springframework.beans.BeansException;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.stereotype.Component;

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;


/**
 * service 处理器适配器
 * 服务端需根据客户端传递过来的RpcRequest对象
 * 通过反射，动态代理技术，最终执行目标方法
 */

public class ServiceHandlerAdapter extends ChannelInboundHandlerAdapter {


    private ApplicationContext applicationContext;

    public ServiceHandlerAdapter(ApplicationContext applicationContext) {
        this.applicationContext = applicationContext;
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object object) throws Exception {


        RpcRequest rpcRequest = (RpcRequest) object;

        Class<?> targetClass = Class.forName(rpcRequest.getClassName());

        Object bean;
        try {
            bean = applicationContext.getBean(targetClass);
        } catch (BeansException e) {
            System.out.println("No such bean " + targetClass.getName());
            ctx.writeAndFlush("404 not found");
            return;
        }
        if (bean == null) {
            ctx.writeAndFlush("404 not found");
            return;
        }
        String targetMethodSimpleName = rpcRequest.getMethodName();

        if (targetMethodSimpleName.contains(".")) {
            targetMethodSimpleName = targetMethodSimpleName.substring(targetMethodSimpleName.lastIndexOf(".") + 1);
        }
        Method targetMethod = targetClass.getMethod(targetMethodSimpleName, rpcRequest.getParameterTypes());
        Object result = targetMethod.invoke(bean, rpcRequest.getParameters());
        ctx.writeAndFlush(result);


    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        super.exceptionCaught(ctx, cause);
    }


}
